'''
Created on 30 Nov 2012

@author: quirino.brizi
'''
import unittest
from cupy.session import Session
from cupy.authentication import BasicAuthentication, DigestAuthentication
from cupy.security import SSLSecurityHandler, Certificate
from cupy.exceptions import CurlRequestException
from cupy.messages import Request
from cupy.enums import Options, Method
from time import sleep

debugFlag = False

class SessionTest(unittest.TestCase):
    '''
    Session testing module
    '''

    def test_init_default(self):
        ses = Session()
        self.assertIsNotNone(ses, "Unable creating default session")
        self.assertIsNotNone(ses.pool, "Internal pool not created")
        
        maxsize = ses.pool.maxsize
        self.assertEquals(1, maxsize, "Expected maxsize 10, got %d" % maxsize)
        
        block = ses.pool.block
        self.assertFalse(block, "Expected block parameter to be False got True")
        
    def test_init_custom(self):
        conf =  {'pool':{"host": "http://myhost.com", 
                   "port":8080, "maxsize":5, "block":False}}
        ses = Session(config=conf)
        self.assertIsNotNone(ses, "Unable creating default session")
        self.assertIsNotNone(ses.pool, "Internal pool not created")
        
        maxsize = ses.pool.maxsize
        self.assertEquals(5, maxsize, "Expected maxsize 5, got %d" % maxsize)
        
        block = ses.pool.block
        self.assertFalse(block, "Expected block parameter to be False got True")
        
        host = ses.pool.host
        self.assertEquals("http://myhost.com", host, 
                          "Expected host: http://myhost.com, got %s" % host)
        
        port = ses.pool.port
        self.assertEquals(8080, port, "Expected port 8080, got %d" % port)
        
    def test_request(self):
        conf =  {'pool':{"maxsize":1, "block":False}}
        ses = Session(config=conf)
        
        opt = {Options.ALLOWREDIRECT:True, Options.MAXREDIRS:3}
        req = Request(url="http://localhost:8000", opt=opt)
        
        resp = ses.exchange([req])
        
        self.assertIsNotNone(resp[0], "Invalid response")
        self.assertIsNotNone(resp[0].get_body(), "Got empty body request")
        self.assertIsNotNone(resp[0].get_info(), "Got empty transaction info")
    
    def test_request_qs(self):
        conf =  {'pool':{"maxsize":1, "block":False}}
        ses = Session(config=conf)
        
        opt = {Options.ALLOWREDIRECT:True, Options.MAXREDIRS:3}
        qs = {'q':'house'}
        
        req = Request(url="http://localhost:8000", opt=opt, qs=qs)
        resp = ses.exchange(req)
        
        self.assertIsNotNone(resp[0], "Invalid response")
        self.assertIsNotNone(resp[0].get_body(), "Got empty body request")
        self.assertIsNotNone(resp[0].get_info(), "Got empty transaction info")
        self.assertEquals("http://localhost:8000?q=house", resp[0].get_url(), 
            "Expected URL: http://localhost:8000?q=house, got %s" % resp[0].get_url())
        
    def test_request_post_data(self):
        conf =  {'pool':{"maxsize":1, "block":False}}
        ses = Session(config=conf)
        
        headers = {"Content-type":"text/plain"}
        opt = {Options.ALLOWREDIRECT:True, Options.MAXREDIRS:3}
        
        req = Request(url="http://localhost:8000", method=Method.POST, 
                      hdr=headers, data="Payload", opt=opt)
        
        resp = ses.exchange(req)
        self.assertIsNotNone(resp, "Got None response")
        self.assertEquals('200', resp[0].get_headers().get("code"))
    
    def test_request_auth_basic(self):
        conf =  {'pool':{"maxsize":1, "block":False}}
        ses = Session(config=conf)
        auth = BasicAuthentication("quirino", "quirino")
        opt = {Options.ALLOWREDIRECT:True, Options.MAXREDIRS:3}
        qs = {'q':'house'}
        
        req = Request(url="http://localhost:8000", qs=qs, auth=auth, opt=opt)
        
        resp = ses.exchange(req)
        self.assertIsNotNone(resp[0], "Invalid response")
        self.assertIsNotNone(resp[0].get_body(), "Got empty body request")
        self.assertIsNotNone(resp[0].get_info(), "Got empty transaction info")
        self.assertEquals("http://localhost:8000?q=house", resp[0].get_url(), 
            "Expected URL: http://localhost:8000?q=house, got %s" % resp[0].get_url())
    
    def test_request_auth_digest(self):
        conf =  {'pool':{"maxsize":1, "block":False}}
        ses = Session(config=conf)
        
        auth = DigestAuthentication("quirino", "quirino")
        opt = {Options.ALLOWREDIRECT:True, Options.MAXREDIRS:3}
        qs = {'q':'house'}
        
        req = Request(url="http://localhost:8000", qs=qs, auth=auth, opt=opt)
        
        resp = ses.exchange(req)
        self.assertIsNotNone(resp[0], "Invalid response")
        self.assertIsNotNone(resp[0].get_body(), "Got empty body request")
        self.assertIsNotNone(resp[0].get_info(), "Got empty transaction info")
        self.assertEquals("http://localhost:8000?q=house", resp[0].get_url(), 
            "Expected URL: http://localhost:8000?q=house, got %s" % resp[0].get_url())
    
    def test_request_security_SSL_base(self):
        conf =  {'pool':{"maxsize":1, "block":False}}
        ses = Session(config=conf)
        
        cert = Certificate()
        security = SSLSecurityHandler(cert)
        qs = {'q':'house'}
        opt = {Options.ALLOWREDIRECT:True, Options.MAXREDIRS:3}
        
        req = Request(url="https://localhost:8000", qs=qs, sec=security, opt=opt)
        try :
            ses.exchange(req)
        except CurlRequestException :
            self.assertTrue(True)
            
    def test_request_debug_function(self):
        self.debugFlag = False
        req = Request("http://localhost:8000", qs={'q':'house'}, 
                      opt={Options.DEBUGFUNCTION: self.debug})
        conf =  {'pool':{"maxsize":1, "block":False}}
        ses = Session(config=conf)
        resp = ses.exchange([req])
        
        self.assertIsNotNone(resp[0])
        self.assertTrue(debugFlag)
        
    def test_get_async_session(self):
        session = Session(config={'pool':{'maxsize':5, 'block':True}}, async=True)
        
        requests = []
        for _ in xrange(5):
            requests.append(Request("http://localhost:8000"))
        
        futures = session.exchange(requests)
        self.assertEquals(5, len(futures))
        times = []
        for future in futures:
            if future.isready() and not future.iscollected():
                try :
                    resp = future.get()
                    self.assertIsNotNone(resp)
                    info = resp.get_info()
                    self.assertIsNotNone(info)
                    times.append(info['TOTAL_TIME'])
                except :
                    continue
            sleep(0.3)
        
        avg = sum(times)/ float(len(times))
        self.assertTrue(avg > 0)

    def debug(self, debug_type, debug_msg):
        global debugFlag
        debugFlag = True
        
if __name__ == "__main__" :
    unittest.main()